/*!
\copyright  Copyright (c) 2024 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
\file       streaming_statistics_reader.c
*/

#include "../streaming_statistics_reader.h"
#include "../streaming_statistics_utils.h"
#include <panic.h>
#include <stdlib.h>
#include <logging.h>
#include "context_types.h"
#include "kymera_data.h"
#include "kymera_le_audio.h"
#include "vm/vm_if.h"
#include <vm.h>

#define STREAMING_IS_LOSSLESS_INDICATOR 0xaf
#define STREAMING_MICROSECONDS_BEFORE_REFRESH (uint32_t)100000
#define STREAMING_RTP_HEADER_SIZE (uint32_t)12
#define STREAMING_MICROSECONDS_IN_SECOND 1000000

static vm_transform_query_bitrate_t prev_bitrate_info = {0};
static uint32_t prev_bitrate = 0;

static inline Transform streamingStatistics_getPacketiser(void)
{
    kymeraTaskData *theKymera = KymeraGetTaskData();
    Transform packetiser = NULL;
#ifdef INCLUDE_MIRRORING
    packetiser = theKymera->hashu.packetiser;
#elif INCLUDE_STEREO
    packetiser = theKymera->packetiser;
#endif
    return packetiser;
}

bool StreamingStatistics_IsA2dpLossless(void)
{
    Transform packetiser = streamingStatistics_getPacketiser();
    uint32 ssrc=0;

    if (packetiser && TransformQuery(packetiser, VM_TRANSFORM_QUERY_PACKETISE_SSRC ,&ssrc))
    {
        return StreamingStatistics_HasLosslessIndicator(ssrc);
    }

    return FALSE;
}

static inline bool streamingStatistics_NeedFreshBitrate(void)
{
#if defined(ENABLE_BITRATE_STATISTIC)
    /* Check how long since last request */
    bool fetchNew = TRUE;
    if (prev_bitrate_info.timestamp > 0)
    {
        uint32_t timestamp = VmGetTimerTime();
        if (timestamp > prev_bitrate_info.timestamp)
        {
            fetchNew = (timestamp - prev_bitrate_info.timestamp) > STREAMING_MICROSECONDS_BEFORE_REFRESH;
        }
    }

    if (!fetchNew)
    {
        DEBUG_LOG_VERBOSE("streamingStatistics_GetBitRate Not fetching new");
        return FALSE;
    }
#endif
    return TRUE;
}

static inline bool streamingStatistics_GetA2dpBitrateInfo(vm_transform_query_bitrate_t *bitrate_info)
{
    *bitrate_info = (vm_transform_query_bitrate_t) {0};
#if defined(ENABLE_BITRATE_STATISTIC)
    /* Check how long since last request */
    bool fetchNew = TRUE;
    if (prev_bitrate_info.timestamp > 0)
    {
        uint32_t timestamp = VmGetTimerTime();
        if (timestamp > prev_bitrate_info.timestamp)
        {
            fetchNew = (timestamp - prev_bitrate_info.timestamp) > STREAMING_MICROSECONDS_BEFORE_REFRESH;
        }
    }

    if (!fetchNew)
    {
        DEBUG_LOG_VERBOSE("streamingStatistics_GetBitRate Not fetching new");
        *bitrate_info = prev_bitrate_info;
        return TRUE;
    }

    /* We need to fetch again as suitable time has elapsed */
    Transform packetiser = streamingStatistics_getPacketiser();

    if (packetiser && TransformQuery(packetiser, VM_TRANSFORM_QUERY_BITRATE ,(uint32 *)bitrate_info))
    {
        return TRUE;
    }
#endif
    return FALSE;
}

bool StreamingStatistics_ReadLeaAptxAdaptiveStreamingStatistics(context_streaming_info_t *streaming_stats)
{
    uint32 lossless_info;
    bool status = KymeraLeAudio_GetAptxAdaptiveLossLessInfo(&lossless_info);
    streaming_stats->type = CONTEXT_STREAMING_STATISTICS_TYPE_LEA;
    streaming_stats->common.is_adaptive = TRUE;
    streaming_stats->common.is_lossless = lossless_info >> 24;
    streaming_stats->common.bitrate = (lossless_info & 0xFFFF) * StreamingStatistics_GetBitrateFactor();

    return status;
}

bool StreamingStatistics_ReadLc3StreamingStatistics(context_streaming_info_t *streaming_stats)
{
    UNUSED(streaming_stats);
    return FALSE;
}

bool StreamingStatistics_ReadA2dpBitrate(uint32_t *bitrate)
{
    vm_transform_query_bitrate_t bitrate_info = {0};

    if(!streamingStatistics_NeedFreshBitrate())
    {
        *bitrate = prev_bitrate;
        return TRUE;
    }

    if(streamingStatistics_GetA2dpBitrateInfo(&bitrate_info))
    {
        StreamingStatistics_CalculateBitrate(prev_bitrate_info, bitrate_info, bitrate);

        // Update previous values even if the call fails.
        memcpy(&prev_bitrate_info, &bitrate_info, sizeof(vm_transform_query_bitrate_t));
        prev_bitrate = *bitrate;
        return TRUE;
    }

    return FALSE;
}

bool StreamingStatistics_ReadTtpHistogram(audio_a2dp_ttp_toa_delta_histogram_t* ttp_histogram)
{
    UNUSED(ttp_histogram);
    return FALSE;
}

bool StreamingStatistics_ReadSeqnErrors(uint32* seqn_errors)
{
    UNUSED(seqn_errors);
    return FALSE;
}